<!-- 
  省市区三级联动选择器组件
  使用方式：
  <region-cascader v-model="formData.region" placeholder="请选择省市区" />
  同时支持纯汉字和区域编码
  参考: 
  - https://blog.csdn.net/jiede8624/article/details/136160162
  - https://blog.csdn.net/m0_63209237/article/details/134030737
-->
<template>
  <div class="region-cascader-wrapper">
    <el-cascader
      v-model="localValue"
      :options="regionOptions"
      :placeholder="placeholder"
      :disabled="disabled"
      :clearable="clearable"
      :filterable="filterable"
      :size="size"
      @change="handleChange"
      class="region-cascader"
    />
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { 
  provinceAndCityData, 
  regionData, 
  pcaTextArr,
  codeToText, 
} from 'element-china-area-data'

// 组件属性
const props = defineProps({
  modelValue: {
    type: [String, Array],
    default: ''
  },
  placeholder: {
    type: String,
    default: '请选择省市区'
  },
  disabled: {
    type: Boolean,
    default: false
  },
  clearable: {
    type: Boolean,
    default: true
  },
  filterable: {
    type: Boolean,
    default: true
  },
  size: {
    type: String,
    default: 'default'
  },
  separator: {
    type: String,
    default: '/'
  },
  // 使用纯汉字数据还是区域编码数据
  useCodeData: {
    type: Boolean,
    default: false
  },
  // 是否输出/接收编码格式的值
  returnCode: {
    type: Boolean,
    default: false
  },
  // 选择级别：1-省, 2-市, 3-区/县
  level: {
    type: Number,
    default: 3,
    validator: (val) => [1, 2, 3].includes(val)
  }
})

const emit = defineEmits(['update:modelValue', 'change'])

// 创建自己的 TextToCode 映射对象（因为library不提供）
const TextToCode = computed(() => {
  const map = {};
  
  // 遍历 codeToText 对象，反向生成映射
  Object.keys(codeToText).forEach(code => {
    const text = codeToText[code];
    if (text) {
      map[text] = code;
    }
  });
  
  return map;
});

// 根据级别选择合适的数据源
const regionOptions = computed(() => {
  if (props.useCodeData) {
    // 使用带编码的数据
    switch (props.level) {
      case 1: 
        return provinceAndCityData.map(item => ({
          value: item.value,
          label: item.label,
          children: []
        }));
      case 2: 
        return provinceAndCityData;
      case 3:
      default: 
        return regionData;
    }
  } else {
    // 使用纯汉字数据
    switch (props.level) {
      case 1: 
        return pcaTextArr.map(item => ({
          value: item.value,
          label: item.label,
          children: []
        }));
      case 2: 
        return pcaTextArr.map(item => ({
          value: item.value,
          label: item.label,
          children: item.children
        }));
      case 3:
      default: 
        return pcaTextArr;
    }
  }
});

// 本地值
const localValue = ref([])

// 检查值是否为编码格式
const isCodeFormat = (value) => {
  if (!value || !Array.isArray(value) || value.length === 0) return false;
  // 编码通常是6位数字字符串
  return /^\d{6}$/.test(value[0]);
};

// 将编码转换为文本
const codeToTextArray = (codes) => {
  if (!codes || !Array.isArray(codes) || codes.length === 0) return [];
  
  const texts = [];
  for (let i = 0; i < codes.length; i++) {
    const code = codes[i];
    if (code && codeToText[code]) {
      texts.push(codeToText[code]);
    }
  }
  return texts;
};

// 将文本转换为编码
const textToCodeArray = (texts) => {
  if (!texts || !Array.isArray(texts) || texts.length === 0) return [];
  
  const codes = [];
  try {
    for (let i = 0; i < texts.length; i++) {
      const text = texts[i];
      const code = TextToCode.value[text];
      if (text && code) {
        codes.push(code);
      }
    }
    return codes;
  } catch (error) {
    console.error('文本转编码失败:', error);
    return [];
  }
};

// 选择变更时的处理函数
const handleChange = (value) => {
  console.log('地区选择变更:', value);
  
  if (!value || value.length === 0) {
    emit('update:modelValue', props.returnCode ? [] : '');
    emit('change', props.returnCode ? [] : '');
    return;
  }
  
  // 根据是否需要返回编码进行转换
  if (props.returnCode) {
    // 如果当前值已经是编码，直接返回
    if (props.useCodeData) {
      emit('update:modelValue', value);
      emit('change', value);
    } else {
      // 如果是纯汉字选择器，需要转换为编码
      const codes = textToCodeArray(value);
      emit('update:modelValue', codes);
      emit('change', codes);
    }
  } else {
    // 返回文本字符串
    let texts = value;
    if (props.useCodeData) {
      // 如果使用的是编码数据，需要转换为文本
      texts = codeToTextArray(value);
    }
    const textString = texts.join(props.separator);
    emit('update:modelValue', textString);
    emit('change', textString);
  }
}

// 初始化本地值
const initLocalValue = () => {
  const value = props.modelValue;
  
  if (!value || (typeof value === 'string' && value.trim() === '') || (Array.isArray(value) && value.length === 0)) {
    localValue.value = [];
    return;
  }
  
  if (typeof value === 'string') {
    // 字符串格式: "浙江省/杭州市/西湖区" 或 "浙江省,杭州市,西湖区"
    const sep = value.includes(props.separator) ? props.separator : ',';
    const parts = value.split(sep);
    
    if (props.useCodeData) {
      // 如果使用编码数据但输入是文本，需要转换
      const codes = textToCodeArray(parts);
      localValue.value = codes;
    } else {
      // 纯文本数据，直接使用
      localValue.value = parts;
    }
  } else if (Array.isArray(value)) {
    // 数组格式: 可能是编码数组或文本数组
    if (props.useCodeData) {
      // 使用编码数据
      if (isCodeFormat(value)) {
        // 已经是编码格式
        localValue.value = value;
      } else {
        // 文本数组，转换为编码
        const codes = textToCodeArray(value);
        localValue.value = codes;
      }
    } else {
      // 使用纯文本数据
      if (isCodeFormat(value)) {
        // 编码数组，转换为文本
        const texts = codeToTextArray(value);
        localValue.value = texts;
      } else {
        // 已经是文本数组
        localValue.value = value;
      }
    }
  }
  console.log('初始化本地值:', localValue.value);
}

// 监听外部传入的值变化
watch(() => props.modelValue, () => {
  console.log('外部值变化:', props.modelValue);
  initLocalValue();
}, { immediate: true, deep: true });

// 监听数据源类型变化
watch(() => props.useCodeData, () => {
  console.log('数据源类型变化，重新初始化');
  initLocalValue();
});

// 组件挂载后执行初始化
onMounted(() => {
  initLocalValue();
})
</script>

<style lang="scss" scoped>
.region-cascader {
  width: 100%;
  
  :deep(.el-input__inner:focus) {
    border-color: var(--el-color-primary);
  }
  
  :deep(.el-cascader__dropdown) {
    .el-cascader-node.is-active {
      color: var(--el-color-primary);
    }
    
    .el-cascader-node.in-active-path {
      color: var(--el-color-primary);
    }
    
    .el-cascader-node__label {
      padding-left: 8px;
    }
    
    .el-cascader-node.is-active .el-cascader-node__label {
      color: var(--el-color-primary);
      font-weight: bold;
    }
  }
}

.region-cascader-wrapper {
  width: 100%;
}
</style> 